/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - core/containers
// Copyright( c) 2014.  All Rights Reserved
//
// File:		AECachedHashMap.h
// Author:		Gianluca Belardelli
// Date:		20/10/2014
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AECACHEDHASHMAP_H_
#define _AECACHEDHASHMAP_H_

template <typename Operations, typename AEAllocator>
class AECachedHashMap
{
	typedef AECachedHashMap<Operations, AEAllocator> ThisType;

// Members
protected:
	struct Elem
	{
		AEUINT32 uiHash;
		AEUINT32 uiKey;
		AEUINT32 uiValue;
	};

	Elem 		*m_lpElem;
	AEINT32 	m_uiNumElems;
	AEINT32 	m_uiHashMod; // capacity - 1
	Operations	m_objOps;

// Methods
protected:
	void _resizeTable( AEINT32 nNewCapacity );

public:
	AE_DECLARE_NONVIRTUAL_CLASS_ALLOCATOR( TOBEDEFINED, ThisType );

	/// AECachedHashMapIterator class.
	/// All iterators are invalidated after a mutating operation. i.e., insertion,removal
	typedef class Dummy *AECachedHashMapIterator;

	/// Create an empty String map.
	AECachedHashMap( Operations ops = Operations() );

	/// Destroy a String map.
	~AECachedHashMap( void );

	/// Get an AECachedHashMapIterator over the keys of this map.
	AECachedHashMapIterator GetIterator( void ) const;

	/// Get the key at AECachedHashMapIterator i.
	AEUINT32 GetKey( AECachedHashMapIterator itIter ) const;

	/// Get the value at AECachedHashMapIterator i.
	AEUINT32 GetValue( AECachedHashMapIterator itIter ) const;

	/// Overwrite the value at AECachedHashMapIterator i.
	void SetValue( AECachedHashMapIterator itIter, AEUINT32 uiValue );

	/// Get the next AECachedHashMapIterator after i.
	AECachedHashMapIterator GetNext( AECachedHashMapIterator itIter ) const;

	/// Return if the AECachedHashMapIterator has reached the end.
	AEBOOL32 IsValid( AECachedHashMapIterator itIter ) const;

	/// Insert key with associated value val.
	/// If key already exists it is overwritten. The string storage is not
	/// copied and must exist for the lifetime of the key.
	void Insert( AEUINT32 uiKey, AEUINT32 uiVal );

	/// Get an AECachedHashMapIterator at 'key'. Check if key was found with isValid().
	AECachedHashMapIterator FindKey( AEUINT32 uiKey ) const;

	/// Find the given key or insert it with the supplied value if not found.
	AECachedHashMapIterator FindOrInsertKey( AEUINT32 uiKey, AEUINT32 uiVal );

	/// Shortcut for isValid(findKey(key)).
	AEBOOL32 HasKey( AEUINT32 uiKey ) const;

	/// Return the value associated with key or if not present, insert and return 'ifNotFound'.
	AEUINT32 GetOrInsert( AEUINT32 uiKey, AEUINT32 uiNotFound );

	/// Return the value associated with key or def if not present.
	AEUINT32 GetWithDefault( AEUINT32 uiKey, AEUINT32 uiDefault ) const;

	/// If key present, write value into out and return HK_SUCCESS. Otherwise return HK_FAILURE.
	AEUINT32 Get( AEUINT32 uiKey, AEUINT32 *lpOut ) const;

	/// Remove pair at AECachedHashMapIterator.
	void Remove( AECachedHashMapIterator itIter );

	/// If key present, remove it and return HK_SUCCESS. Otherwise return HK_FAILURE.
	AEUINT32 Remove( AEUINT32 uiKey );

	/// Return the number of keys.
	AEINT32 GetSize( void ) const;

	/// Perform an internal consistency check.
	AEBOOL32 IsOk( void ) const;

	/// Assignment operator. Will copy the memory chunk.
	AECachedHashMap &operator=( const AECachedHashMap *lpOther );

	/// Remove all keys from the map.
	void Clear( void );

	/// Swap all data with another map.
	void Swap( AECachedHashMap &refOther );

	/// Insert keys from other into this, overwriting duplicates.
	void Merge( const AECachedHashMap &refOther );

	AEINT32 GetCapacity( void ) const;

	/// Reserve space for at least numElements;
	void Reserve( AEINT32 nNumElements );
};

#include "AECachedHashMap.inl"

#endif // _AECACHEDHASHMAP_H_
